package com.sky.task;

import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 自定义定时任务类, 定时处理订单状态
 * 搭配spring task使用,用来定时调用任务
 * 这是定时的处理相应的逻辑,,所以都不用去设计接口,,因为这个类,会自动的调用这个处理的方法,比如凌晨1点自动运行
 */
@Component
@Slf4j
public class OrderTask {

    @Autowired   //因为这个类有@Component注解,说明是在容器中的,,因此是可以通过@Autowired进行注入的
    private OrderMapper orderMapper;
    
    /**
     * 处理超时订单的方法
     */
    @Scheduled(cron = "0 * * * * ? ")    //指定cron表达式,,,这里是每分钟触发一次
    public void processTimeoutOrder(){
        
        log.info("定时处理订单超时: {}", LocalDateTime.now());
        //因为这个方法是自动触发,,所以,测试完就把上面log输出注释掉了,要不控制台总输出
        
        //当前时间 -15分钟,怎么算,可以用提供好的方法
            //plusMinutes虽然表示加多少分钟,但是我们传入-15就可以了,,让我想到了补码的加减
        LocalDateTime time = LocalDateTime.now().plusMinutes(-15);
         
        //查询有哪些超时订单   (不超时就不用处理)
            //select * from orders where status = ? and order_time < (当前时间 - 15分钟)
        List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time);
        //PENDING_PAYMENT这个常量值为1,表示未支付的订单状态
        
        //遍历这个集合,,,处理对应的订单状态,,修改为"已取消"
        if(ordersList != null && ordersList.size() > 0){
            for (Orders orders : ordersList) {
                orders.setStatus(Orders.CANCELLED);   //这个常量值6:  就表示已取消的状态
                orders.setCancelReason("订单超时,自动取消");       //设置取消的原因
                orders.setCancelTime(LocalDateTime.now());   //取消的时间
                
                //更新状态
                orderMapper.update(orders);
            }
        }
        
    }

    /**
     * 处理一直处于"派送中"状态的订单
     * 其实下面的常量值,,不是只标记的数字,不知道是什么意思,,其实也可以通过ctrl+b,跳进去查看定义,,不只是方法可以这样用
     */
    @Scheduled(cron = "0 0 1 * * ?")   //指定cron表达式,这里是每天凌晨1点,触发1次
    //@Scheduled(cron = "0/5 * * * * ?")  //这里是为了控制台测试的,,每5秒触发一次,要不等到凌晨1点,不太现实
    public void processDeliveryOrder(){
        
        log.info("定时处理处于派送中的订单: {}",LocalDateTime.now());
        //因为这个方法是自动触发,,所以,测试完就把上面log输出注释掉了,要不控制台总输出
        
        //当前时间 -1小时
        LocalDateTime time = LocalDateTime.now().plusHours(-1);

        //查询有哪些超时订单   (不超时就不用处理)
            //select * from orders where status = ? and order_time < (当前时间 - 1小时)
            //这里为啥要减1个小时,那不就相当于变成凌晨0点,那就说明处理的是今天以前的所有订单,,厉害,这里自己就不敢想
                //即处理今天以前所有,订单处于"派送中"的订单,修改状态为""
        List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, time);
        //这个常量值为4,表示派送中的状态

        //遍历这个集合,,,处理对应的订单状态,,修改为"已取消"
        if(ordersList != null && ordersList.size() > 0){
            for (Orders orders : ordersList) {
                orders.setStatus(Orders.COMPLETED);   //这个常量值5:  就表示已完成的状态
 
                //更新状态
                orderMapper.update(orders);
            }
        }
        
    }
    
    
}
